package com.wyman.context.event;

import com.wyman.context.ApplicationContext;
import com.wyman.context.ApplicationContextAware;
import com.wyman.context.ApplicationEvent;
import com.wyman.context.ApplicationListener;
import com.wyman.factory.BeanFactory;
import com.wyman.factory.BeanFactoryAware;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * @Author 李伟民
 * @Description 实现通用的非核心业务方法 比如添加删除监听器 获取bean所在的bean工厂
 * @DateTime 2024/12/18 00:40
 */
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster, BeanFactoryAware {


    public Set<ApplicationListener<ApplicationEvent>> applicationListeners = new LinkedHashSet<>();
    private BeanFactory beanFactory;

    @Override
    public void addApplicationListener(ApplicationListener<?> applicationListener) {
        applicationListeners.add((ApplicationListener<ApplicationEvent>) applicationListener);
    }

    @Override
    public void removeApplicationListener(ApplicationListener<?> applicationListener) {
        applicationListeners.remove(applicationListener);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    //获取支持处理事件的监听器
    public ArrayList<ApplicationListener> getApplicationListeners(ApplicationEvent event){
        ArrayList<ApplicationListener> listeners = new ArrayList<>();
        for(ApplicationListener applicationListener:applicationListeners){
            if(supportEvent(event,applicationListener)){
                listeners.add(applicationListener);
            }
        }
        return listeners;
    }

    private boolean supportEvent(ApplicationEvent event,ApplicationListener listener){
        Class<? extends ApplicationListener> listenerClass = listener.getClass();
        //这里只支持一种 用反射实例化的 代码意思是获取由listener实现的接口类型 以及对应接口的泛型信息 即具体实现了哪种Event这里可以拿到ApplicationListener<>
        Type genericInterfaces = listenerClass.getGenericInterfaces()[0];
        //先将type转成 ParameterizedType类型 再调用类型的getActualTypeArguments()获取所有的泛型类型
        Type argumentGenericType = ((ParameterizedType)genericInterfaces).getActualTypeArguments()[0];
        String className = argumentGenericType.getTypeName();
        Class<?> clazz;
        try {
            clazz = Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        // a instanceof b a是b儿子 a.isAssignFrom(b) b可以转换成a  即b是不是a得爹
        //这里Listener泛型类型是是一个Event类型  监听器的处理的事件是不是待发布事件的爹 如果是 能处理
        return clazz.isAssignableFrom(event.getClass());
    }

}
